#pragma once
#include "../mqcommon/Log.hpp"
#include "../mqcommon/Helper.hpp"
#include "../mqcommon/Message.pb.h"

#include <iostream>
#include <vector>
#include <string>

namespace ouyangmq
{
    class Router
    {
    public:
        // 1. 判定routing_key是否合法
        // 只含有( a~z, A~Z, 0~9, _, . )
        static bool isLegalRoutingKey(const std::string &routingKey)
        {
            for (const auto &ch : routingKey)
            {
                if ((ch >= 'a' && ch <= 'z') ||
                    (ch >= 'A' && ch <= 'Z') ||
                    (ch >= '0' && ch <= '9') ||
                    ch == '_' || ch == '.')
                {
                    continue;
                }
                return false;
            }
            return true;
        }

        // 2. 判定binding_key是否合法
        // 只含有( a~z, A~Z, 0~9, _, ., #, *)
        // *#是通配符, 独立存在, *和#不能连续出现
        // news.*.# --> error|news.#.* --> error|news.#.# --> error|news.*.* --> OK
        // news.music#.*|news.music*.# --> error 通配符不可以和其他的字符一起出现
        static bool isLegalBindingKey(const std::string &bindingKey)
        {
            for (const auto &ch : bindingKey)
            {
                if ((ch >= 'a' && ch <= 'z') ||
                    (ch >= 'A' && ch <= 'Z') ||
                    (ch >= '0' && ch <= '9') ||
                    ch == '_' || ch == '.' ||
                    ch == '#' || ch == '*')
                {
                    continue;
                }
                // LogModule::LOG(LogModule::LogLevel::DEBUG) << "字符含有问题!";
                return false;
            }

            std::vector<std::string> result;
            HelperModule::SplitHelper::split(bindingKey, ".", result);
            for (auto &s : result)
            {
                // 如果s字符串的大小 > 1 && 出现了*/#就是错误的格式
                if ((s.size() > 1) &&
                        (s.find("*") != std::string::npos ||
                    s.find("#") != std::string::npos))
                {
                    // LogModule::LOG(LogModule::LogLevel::DEBUG) << s;
                    // LogModule::LOG(LogModule::LogLevel::DEBUG) << s.size();
                    // LogModule::LOG(LogModule::LogLevel::DEBUG) << "字符包含#/*问题!";
                    return false;
                }
            }

            for (int i = 1; i < result.size(); ++i)
            {
                if (result[i] == "#" && result[i - 1] == "*")
                {
                    // LogModule::LOG(LogModule::LogLevel::DEBUG) << "#和*连续问题";
                    return false;
                }
                if (result[i] == "#" && result[i - 1] == "#")
                {
                    // LogModule::LOG(LogModule::LogLevel::DEBUG) << "#和#连续问题";
                    return false;
                }
                if (result[i] == "*" && result[i - 1] == "#")
                {
                    // LogModule::LOG(LogModule::LogLevel::DEBUG) << "*和#连续问题";
                    return false;
                }
            }

            return true;
        }

        // 3. 路由匹配模块
        // 广播/直接/主题
        static bool route(ExchangeType type, const std::string &routingKey, const std::string &bindingKey)
        {
            if (type == ExchangeType::BROADCAST)
            {
                // 广播
                return true;
            }
            else if (type == ExchangeType::DIRECT)
            {
                // 直接
                return (routingKey == bindingKey);
            }
            else if (type == ExchangeType::THEME)
            {
                // 主题
                // 匹配规则 --> 动态规划的思想
                return matchTopic(routingKey, bindingKey);
            }
            else
            {
                LogModule::LOG(LogModule::LogLevel::ERROR) << "交换机类型错误";
                abort();
            }
        }

    private:
        static bool matchTopic(const std::string &routingKey, const std::string &bindingKey)
        {
            // 分割routingKey和bindingKey为单词列表
            std::vector<std::string> resultb; // bindingKey分割结果
            std::vector<std::string> resultr; // routingKey分割结果
            HelperModule::SplitHelper::split(bindingKey, ".", resultb);
            HelperModule::SplitHelper::split(routingKey, ".", resultr);

            // 创建DP表并初始化
            int n = resultr.size();
            int m = resultb.size();
            std::vector<std::vector<int>> dp(m + 1, std::vector<int>(n + 1, 0));

            // 匹配初始化
            dp[0][0] = 1;

            // 处理bindingKey以#开头的情况（可匹配空routingKey）
            if (m > 0 && resultb[0] == "#")
            {
                dp[1][0] = 1;
            }

            // 填充DP表
            for (int j = 1; j <= m; ++j)
            {
                for (int i = 1; i <= n; ++i)
                {
                    const std::string &bWord = resultb[j - 1];
                    const std::string &rWord = resultr[i - 1];

                    if (bWord == rWord)
                    {
                        // 单词完全匹配
                        dp[j][i] = dp[j - 1][i - 1];
                    }
                    else if (bWord == "*")
                    {
                        // *匹配单个层级
                        dp[j][i] = dp[j - 1][i - 1];
                    }
                    else if (bWord == "#")
                    {
                        // #匹配零个或多个层级
                        dp[j][i] = dp[j - 1][i - 1] || // 匹配当前层级
                                   dp[j - 1][i] ||     // 匹配零个层级
                                   dp[j][i - 1];       // 匹配多个层级
                    }
                    else
                    {
                        // 不匹配
                        dp[j][i] = 0;
                    }
                }
            }

            // 返回最终匹配结果
            return dp[m][n] == 1;
        }
    };
}